﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

using ComputerResourceConsole.factory;
using ComputerResourceConsole.lib;
using NGIS.Model;
using ComputerResourceConsole.common;

namespace ComputerResourceConsole.view
{
    public partial class frm_debug : Form
    {
        private IModelServiceDebuggerControl _pMsDebuggerCtrl = null;
        private frm_debug_setting _settingDia = null;

        public frm_debug()
        {
            this._pMsDebuggerCtrl = ComponentControlFactory.createModelServiceDebuggerControl();
            InitializeComponent();

            this.tb_host.Text = "127.0.0.1";
            this.tb_port.Text = "6002";
            this.tb_insID.Text = "3667daec-e545-4d00-9f05-6fcff7e16c85";
        }

        private void btn_selectMDL_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "MDL files (*.mdl)|*.mdl";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                this.tb_MDLPath.Text = ofd.FileName;
                this.setStatusText("Loading MDL...");

                //! Delete all TabPages
                this.tbctrl_states.TabPages.Clear();

                if (!System.IO.File.Exists(this.tb_MDLPath.Text))
                {
                    MessageBox.Show("File does not exist!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }
                try
                {
                    this._pMsDebuggerCtrl.loadMDLFile(this.tb_MDLPath.Text);
                    IModelBehavior behavior = this._pMsDebuggerCtrl.getModelBehavior();
                    int stateCount = behavior.getModelStateCount();
                    this._pMsDebuggerCtrl.clearAllData();
                    for (int index = 0; index < stateCount; index++)
                    {
                        ModelState ms = new ModelState();
                        behavior.getModelState(index, ref ms);
                        string stateName_title = ms.stateName;
                        StateTabPage stateTabPage = new StateTabPage();
                        stateTabPage.loadStateInfo(ms, this._pMsDebuggerCtrl);
                        stateTabPage.ImageIndex = index;
                        this.tbctrl_states.TabPages.Add(stateTabPage);
                    }

                    tb_name.Text = this._pMsDebuggerCtrl.getMDLModelName();
                    tb_uid.Text = this._pMsDebuggerCtrl.getMDLModelUID();
                    tb_category.Text = this._pMsDebuggerCtrl.getMDLCategory();

                    if (stateCount > 0)
                    {
                        this.tbctrl_states.SelectedIndex = 0;
                    }
                    this.setStatusText("Loading MDL finished!");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.setStatusText("Error in loading MDL!");
                }
            }
        }

        private void frm_debug_ResizeEnd(object sender, EventArgs e)
        {
            this.tbctrl_states.Size = new Size(this.Size.Width - 16, this.Size.Height - 214);
        }

        private void setStatusText(string status)
        {
            this.toolStripStatusLabel_status.Text = status;
        }

        private void btn_start_Click(object sender, EventArgs e)
        {
            if (this._pMsDebuggerCtrl.Status == "Started")
            {
                this._pMsDebuggerCtrl.stop();
            }
            else
            {
                //! Check MDL ready loaded
                if (!this._pMsDebuggerCtrl.MDLLoading)
                {
                    MessageBox.Show("Please select a MDL file first!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                //! Check all data ready
                if (!this._pMsDebuggerCtrl.DataReady)
                {
                    MessageBox.Show("Necessary data are not all ready!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                //! Check direction
                if (!this._pMsDebuggerCtrl.DirectoryReady)
                {
                    MessageBox.Show("Necessary directory are not all ready!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                //! Write file
                if (!this._pMsDebuggerCtrl.formatToFile())
                {
                    MessageBox.Show("Can not write config file!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
                }

                //! Start process
                this._pMsDebuggerCtrl.start(this.onDebuggingExit);

                //! Notice
                this.setStatusText("Debugging running...");

                //! Disable components
                this.btn_setting.Enabled = false;
                this.btn_selectMDL.Enabled = false;
                this.tbctrl_states.Enabled = false;

                //! Change debug button function
                this.btn_start.Text = "Stop debugging";
            }
        }

        private void btn_setting_Click(object sender, EventArgs e)
        {
            this._settingDia = new frm_debug_setting();
            this._settingDia.Port = this._pMsDebuggerCtrl.Port;
            if (this._settingDia.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this._pMsDebuggerCtrl.Host = this._settingDia.Host;
                this.tb_host.Text = this._settingDia.Host.ToString();
                this._pMsDebuggerCtrl.Port = this._settingDia.Port;
                this.tb_port.Text = this._settingDia.Port.ToString();
                this._pMsDebuggerCtrl.InstanceID = this._settingDia.InstanceID;
                this.tb_insID.Text = this._settingDia.InstanceID.ToString();
                return;
            }
        }


        private void onDebuggingExit(object sender, EventArgs e)
        {
            if (this.btn_start.InvokeRequired)
            {
                this._pMsDebuggerCtrl.Status = "Stopped";
                CommonMethod.CommonEvent stcb = new CommonMethod.CommonEvent(onDebuggingExit);
                this.Invoke(stcb, new object[] { sender, e });
            }
            else
            {
                //! Enable components
                this.btn_setting.Enabled = true;
                this.btn_selectMDL.Enabled = true;
                this.tbctrl_states.Enabled = true;

                this.setStatusText("Debugging stopped!");
                this.btn_start.Text = "Start debugging";
            }
        }

        private void btn_copyArgs_Click(object sender, EventArgs e)
        {
            Clipboard.SetDataObject(this._pMsDebuggerCtrl.Host + " " + this._pMsDebuggerCtrl.Port + " " + this._pMsDebuggerCtrl.InstanceID, true);
            MessageBox.Show("Copied!", "Notice", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
        }

        private void frm_debug_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this._pMsDebuggerCtrl.Status == "Started")
            {
                this._pMsDebuggerCtrl.stop();
            }
        }
    }

    public partial class StateTabPage : TabPage
    {
        private ModelState _state;
        private DataGridView _dataView;
        private ContextMenu _cellContextMenu;
        private IModelServiceDebuggerControl _pMSDCtrl;
        private int _selectedColumnIndex = 0;
        private int _selectedRowIndex = 0;

        public StateTabPage()
        {
            this._dataView = new DataGridView();
            this._dataView.Dock = DockStyle.Fill;
            this._dataView.ReadOnly = true;
            this._dataView.AllowUserToAddRows = false;

            this._dataView.Columns.Add("Event", "Event");
            this._dataView.Columns.Add("Optional", "Optional");
            this._dataView.Columns.Add("Data", "Data");
            this._dataView.Columns[0].Width = 150;
            this._dataView.Columns[1].Width = 100;
            this._dataView.Columns[2].Width = 300;

            this._dataView.CellDoubleClick += new DataGridViewCellEventHandler(dataView_CellClick);
            this._dataView.CellMouseDown += new DataGridViewCellMouseEventHandler(dataView_CellMouseDown);

            this._cellContextMenu = new ContextMenu();
            //! Location
            MenuItem location = new MenuItem();
            location.Text = "Locate";
            location.Click += new EventHandler(this.cellMenuLocaltionClick);
            this._cellContextMenu.MenuItems.Add(location);

            //! Removing
            MenuItem removing = new MenuItem();
            removing.Text = "Remove";
            removing.Click += new EventHandler(this.cellMenuRemovingClick);
            this._cellContextMenu.MenuItems.Add(removing);

            this.Controls.Add(this._dataView);
        }

        public bool loadStateInfo(ModelState ms, IModelServiceDebuggerControl pCtrl)
        {
            if (ms.stateName == "")
            {
                return false;
            }
            this._state = ms;
            if (pCtrl == null)
            {
                return false;
            }
            this._pMSDCtrl = pCtrl;

            string stateName_title = ms.stateName;
            if (stateName_title.Length > 10)
            {
                stateName_title = stateName_title.Substring(0, 10) + "...";
            }
            base.Name = ms.stateName;
            base.Text = stateName_title;

            int eventsCount = this._state.modelEvents.Count;
            int inputCount = 0;
            for (int index = 0; index < eventsCount; index++)
            {
                if (this._state.modelEvents[index].eventType == EModelEventType.EMET_RESPONSE)
                {
                    this._dataView.Rows.Add(1);
                    this._dataView.Rows[inputCount].Cells[0].Value = this._state.modelEvents[index].eventName;
                    this._dataView.Rows[inputCount].Cells[1].Value = this._state.modelEvents[index].optional.ToString();
                    pCtrl.pushData(ms.stateName, this._state.modelEvents[index].eventName, this._state.modelEvents[index].optional, "");
                    inputCount++;
                }
            }
            
            return true;
        }

        private void dataView_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == 2 && e.RowIndex > -1)
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Filter = "All files (*.*)|*.*";
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    ((DataGridView)sender).Rows[e.RowIndex].Cells[2].Value = ofd.FileName;
                    this._pMSDCtrl.updateData(this._state.stateName, this._dataView.Rows[e.RowIndex].Cells[0].Value.ToString(), ofd.FileName);
                }
            }
        }

        private void dataView_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.ColumnIndex == 2 && e.RowIndex > -1)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Right)
                {
                    if (((DataGridView)sender).Rows[e.RowIndex].Cells[2].Value != null && ((DataGridView)sender).Rows[e.RowIndex].Cells[2].Value.ToString() != "")
                    {
                        this._cellContextMenu.Show(this, new Point(e.X + 292, e.Y + 23*(e.RowIndex + 1)));
                        this._selectedColumnIndex = e.ColumnIndex;
                        this._selectedRowIndex = e.RowIndex;
                    }
                }
            }
        }

        private void cellMenuLocaltionClick(object sender, EventArgs e)
        {
            string filePath = this._dataView.Rows[this._selectedRowIndex].Cells[this._selectedColumnIndex].Value.ToString();

            if (!File.Exists(filePath))
            {
                MessageBox.Show("File does not exist!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this._dataView.Rows[this._selectedRowIndex].Cells[this._selectedColumnIndex].Value = null;
                return;
            }

            string path = Path.GetDirectoryName(filePath);
            string filename = Path.GetFileName(filePath);
            System.Diagnostics.Process.Start("Explorer", "/select," + path + "\\" + filename);
        }


        private void cellMenuRemovingClick(object sender, EventArgs e)
        {
            this._dataView.Rows[this._selectedRowIndex].Cells[this._selectedColumnIndex].Value = "";
            this._pMSDCtrl.updateData(this._state.stateName, this._dataView.Rows[this._selectedRowIndex].Cells[0].Value.ToString(), "");
        }
    }
}
